<?php
ini_set( 'display_errors', '1' );
require_once __DIR__.'/vendor/autoload.php';
use Web3\Web3;
use Web3\Providers\HttpProvider;
use Web3\RequestManagers\HttpRequestManager;
use Web3p\EthereumTx\Transaction;
use Web3\Formatters\HexFormatter;
use Web3\Formatters\QuantityFormatter;
use Web3\Formatters\NumberFormatter;

$web3 = new Web3(new HttpProvider(new HttpRequestManager('https://ropsten.infura.io/v3/8c2ce7fc647f4e7c9f16060d0fa3b34a',15)));
// $web3=new Web3('https://ropsten.infura.io/v3/8c2ce7fc647f4e7c9f16060d0fa3b34a');
$eth = $web3->eth;

// $web3->clientVersion(function ($err, $version) {
//     if ($err !== null) {
//         // do something
//         echo 'ERR'.$err;
//         return;
//     }
//     if (isset($version)) {
//         echo 'Client version: ' . $version;
//     }
// });

//查询余额
// $eth->getBalance('0x2dE2B132046056B86562Cf21E37dDCBC03AC6473',function($err, $balance){
// 	if ($err !== null) {
//         // do something
//         echo 'ERR'.$err;
//         return;
//     }
//     if (isset($balance)) {
//         echo 'Account balance: ' . $balance;
//     }
// });

// 查询当前区块链高度
// $latestBlock=1;
// $eth->blockNumber(function($err,$blockNumber) use ($latestBlock){
// 	if ($err !== null) {
//         // do something
//         echo 'ERR'.$err;
//         return;
//     }
//     if (isset($blockNumber)) {
//         echo 'Latest block number: ' . $blockNumber;
//         $latestBlock=$blockNumber;	
//         // echo "latestBlock: ".$latestBlock;
//     }
// });

// //格式转换：从16进制转换为10进制
// echo 'BlockNumber:'.NumberFormatter::format('0x49319e');

// // 获取指定区块
// $eth->getBlockByNumber("latest",true,function($err,$block){
// 	if($err !== null){
// 		echo 'Err'.$err;
// 		return ;
// 	}
// 	if(isset($block)){
// 		// echo "Block Info: ";
// 		print_r(json_encode($block));
// 	}
// });

// 格式转换
// echo HexFormatter::format("100000000000000000000");
// echo '<br>';
// echo QuantityFormatter::format("100000000000000000000");

// 获取gas Price
// $eth->gasPrice(function($err,$gasPrice){
// 	if($err !== null){
// 		echo 'ERR: '.$err;
// 	}
// 	if(isset($gasPrice)){
// 		echo "current price: ".$gasPrice." Price in hex: ". QuantityFormatter::format($gasPrice);
// 	}
// });

// exit;

// //发起交易
// $fromAddress="0xF5b0A97Eec56D779487d030f3A09D304265DDD46";
// $toAddress="0x2dE2B132046056B86562Cf21E37dDCBC03AC6473";
// $privateKey="0xad783a350520acb763fe90a78803cb1e849b85ab78b3f3d7bcf9535bd4b39a6c";
// $eth->getTransactionCount($fromAddress, 'pending', function ($err, $nonce) use ($eth) {

// 	//echo $nonce;

// 	$fromAddress="0xF5b0A97Eec56D779487d030f3A09D304265DDD46";
// 	$toAddress="0x2dE2B132046056B86562Cf21E37dDCBC03AC6473";
// 	$privateKey="0xad783a350520acb763fe90a78803cb1e849b85ab78b3f3d7bcf9535bd4b39a6c"; //Receiver
// 	$privateKey="0xf404287809ff7d205a46a324231666d51cbad20475683f61117a889166fa8e73"; //Receiver2

//     if ($err !== null) {
//         echo "Error: " . $err->getMessage();
//     }

//     echo HexFormatter::format("100");
//     echo '<br>';
//     echo QuantityFormatter::format("100");

//     $transaction = new Transaction([
//         'nonce' => QuantityFormatter::format(($nonce->toString())),
//         "gasPrice" => "0x77359400",
//         "gasLimit" => QuantityFormatter::format("196022"),
//         'from' => $fromAddress,
//         'to' => $toAddress,
//         'value' => QuantityFormatter::format("1000"),
//         'chainId' => 3
//     ]);
//     /*
//     ChainID:
//     1 	Main net
//     3	Ropsten
//     */
//     /*
//     仍需深究的问题：
//     1. gasPrice怎么确定？ - 看到MetaMast里面可以选择三种级别的Transaction Fee，分别是Fastest、Fast、Slow
//     2. gasLimit怎么确定？ - 可以估算、如果是Transaction操作，Limit是固定的
//     3. 怎么从KeyStore里读取私钥？ - 看看有没有开源组件 - 暂时不考虑用KeyStore存储私钥，而使用简单的对称加密算法加密私钥后存储
//     4. 完整的ChainID对照表？ - 目前只知道 1-MainNet、3-Ropsten
//     5. 搞清楚参数传入格式要求和格式转换方法 - 目前简单采用Web3.php提供的Formatter方法
//     6. 搞清楚nonce的坑 - 已经收藏了相关文章，看看本段示例代码的实现是不是已经避免了坑
//     */

//     $signedTransaction = $transaction->sign($privateKey);

//     //echo $signedTransaction;

//     $eth->sendRawTransaction(sprintf('0x%s', $signedTransaction), function ($err, $tx) {
//         if ($err !== null) {
//             echo "Error: " . $err->getMessage();
//         }
//         echo 'TX: ' . $tx;
//     });
// });

//查询指定地址的交易
function getTransactionsByAddress($eth, $address, $offset=100, $endBlock=null) {
	
	$address=strtolower($address);

	$blockArray=array();
	$txFromAccount=array();
	$txToAccount=array();

	$eth->blockNumber(function($err,$blockNumber) use($eth, $address, $endBlock, $offset, &$blockArray, &$txFromAccount, &$txToAccount) {
		//先取到区块链总区块数量
		if ($err !== null) {
	        // do something
	        echo 'ERR'.$err;
	        return;
	    }
	    if (isset($blockNumber)) {
	    	//整理输入值，如果没有指定从哪个区块开始向前查询，则默认从最后一个区块开始
	    	if($endBlock==null || $endBlock>$blockNumber){
				$endBlock=$blockNumber;
			}
			//根据输入的向前查询区块数量，计算从哪个区块开始查询
			$startBlock=$endBlock->subtract(new \phpseclib\Math\BigInteger($offset));

			//echo "Searching block from $startBlock to $endBlock...";
			//开始根据定义好的查询范围遍历查询区块
			for($i=$startBlock;$i->compare($endBlock);$i=$i->add(new \phpseclib\Math\BigInteger(1))){
				//根据遍历的编号$i查询区块详细内容
				$eth->getBlockByNumber(QuantityFormatter::format($i),true,function($err,$block) use($i, $address, &$blockArray, &$txFromAccount, &$txToAccount){
					if($err !== null){
						echo 'Err'.$err;
						return ;
					}
					if(isset($block)){
						// echo "Block ".$i->toString()." Info: ";
						// print_r(json_encode($block));
						array_push($blockArray, $block);
						//遍历查询当前区块的所有交易
						foreach ($block->transactions as $key => $transaction) {
							//若找到从查询账号转出的交易，加入到转出交易数组
							if($transaction->from == $address){
								array_push($txFromAccount, $transaction);
							}
							//若找到从查询账号收到的交易，加入到收到交易数组
							if($transaction->to == $address){
								array_push($txToAccount, $transaction);
							}
						}

					}
				});
			}
	    }
	});

	// print_r(json_encode($blockArray));
	// 再遍历数据可以做到更多事
	if (count($txFromAccount)>0) {
		print_r(json_encode($txFromAccount));
	}
	if (count($txToAccount)>0) {
		print_r(json_encode($txToAccount));
	}
}
// getTransactionsByAddress($eth,'0x2dE2B132046056B86562Cf21E37dDCBC03AC6473',10);










